package repository

import (
	"context"
	"furniture-server-gin/api/pkg/domain/role"
	"time"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
)

type roleRepository struct {
	collection *mongo.Collection
}

// NewRoleRepository 创建角色仓库实例
func NewRoleRepository(database *mongo.Database) role.Repository {
	return &roleRepository{
		collection: database.Collection("roles"),
	}
}

// Create 创建角色
func (r *roleRepository) Create(role *role.Role) error {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	// 如果ID为空，生成新的ObjectID
	if role.ID == "" {
		role.ID = primitive.NewObjectID().Hex()
	}

	_, err := r.collection.InsertOne(ctx, role)
	return err
}

// Update 更新角色
func (r *roleRepository) Update(role *role.Role) error {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	objectID, err := primitive.ObjectIDFromHex(role.ID)
	if err != nil {
		return err
	}

	filter := bson.M{"_id": objectID}
	update := bson.M{"$set": role}

	_, err = r.collection.UpdateOne(ctx, filter, update)
	return err
}

// Delete 删除角色
func (r *roleRepository) Delete(id string) error {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	objectID, err := primitive.ObjectIDFromHex(id)
	if err != nil {
		return err
	}

	filter := bson.M{"_id": objectID}
	_, err = r.collection.DeleteOne(ctx, filter)
	return err
}

// FindByID 根据ID查找角色
func (r *roleRepository) FindByID(id string) (*role.Role, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	objectID, err := primitive.ObjectIDFromHex(id)
	if err != nil {
		return nil, err
	}

	filter := bson.M{"_id": objectID}
	var role role.Role
	err = r.collection.FindOne(ctx, filter).Decode(&role)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, nil
		}
		return nil, err
	}

	return &role, nil
}

// FindByName 根据名称查找角色
func (r *roleRepository) FindByName(name string) (*role.Role, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	filter := bson.M{"name": name}
	var role role.Role
	err := r.collection.FindOne(ctx, filter).Decode(&role)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, nil
		}
		return nil, err
	}

	return &role, nil
}

// FindAll 查找所有角色
func (r *roleRepository) FindAll() ([]*role.Role, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	cursor, err := r.collection.Find(ctx, bson.M{})
	if err != nil {
		return nil, err
	}
	defer cursor.Close(ctx)

	var roles []*role.Role
	for cursor.Next(ctx) {
		var role role.Role
		if err := cursor.Decode(&role); err != nil {
			return nil, err
		}
		roles = append(roles, &role)
	}

	if err := cursor.Err(); err != nil {
		return nil, err
	}

	return roles, nil
}
